﻿using System;
using System.Linq;
using System.Reflection;
using DevelopmentKit.Extensions.SharpArch.NHibernateMaps.Conventions;
using FluentNHibernate.Automapping;
using FluentNHibernate.Conventions;
using SharpArch.Domain.DomainModel;
using SharpArch.NHibernate.FluentNHibernate;

namespace DevelopmentKit.Extensions.SharpArch.NHibernateMaps
{
    #region Using Directives

    

    #endregion

    /// <summary>
    /// Generates the automapping for the domain assembly
    /// </summary>
    public class AutoPersistenceModelGenerator : IAutoPersistenceModelGenerator
    {

        private readonly string[] _overridesFromAssemblys;
        private readonly string[] _entityAssemblys;

        public AutoPersistenceModelGenerator(string[] overridesFromAssemblys, string[] entityAssemblys)
        {
            this._overridesFromAssemblys = overridesFromAssemblys;
            _entityAssemblys = entityAssemblys;
        }

        public AutoPersistenceModel Generate()
        {
            var mappings =
                AutoMap.Assembly(Assembly.Load( _entityAssemblys.First()), new AutomappingConfiguration());
            if (_entityAssemblys.Count() > 1)
            {
                foreach (var entityAssemblys in _entityAssemblys.Skip(1))
                {
                    mappings.AddEntityAssembly(Assembly.Load(entityAssemblys));
                }

            }

            mappings.IgnoreBase<Entity>();
            mappings.IgnoreBase(typeof(EntityWithTypedId<>));
            mappings.Conventions.Setup(GetConventions());
            if (null != _overridesFromAssemblys && _overridesFromAssemblys.Any())
            {
                foreach (var overridesFromAssembly in _overridesFromAssemblys)
                {
                    mappings.UseOverridesFromAssembly(Assembly.Load(overridesFromAssembly));
                }

            }
            return mappings;
        }

        private static Action<IConventionFinder> GetConventions()
        {
            return c =>
                   {
                       c.Add<PrimaryKeyConvention>();
                       c.Add<CustomForeignKeyConvention>();
                       c.Add<HasManyConvention>();
                       c.Add<TableNameConvention>();
                       c.Add<PropertyConvention>(); 
                       c.Add<ReferenceNotNullConvention>();
                       c.Add<HasManyToManyConvention>();
                   };
        }
    }
}